package main

import (
	"fmt"
	"log"
	"os"
	"sync"
	"time"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/client-go/informers"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/cache"
	"k8s.io/client-go/tools/clientcmd"
)

// 定义变量用于计数
var count int

// 互斥锁
var mu sync.Mutex

// 初始化客户端
func InitClient() (*kubernetes.Clientset, error) {
	config, err := clientcmd.BuildConfigFromFlags("", "../config/kubeconfig")
	if err != nil {
		return nil, err
	}
	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		return nil, err
	}
	return clientset, nil
}

// 监听Pod事件（新增，删除）
func WatchPods(clientset *kubernetes.Clientset) {
	// 创建informer工厂
	factory := informers.NewSharedInformerFactory(clientset, 0)
	// 获取pod infomer
	podInformer := factory.Core().V1().Pods().Informer()
	// 监听pod
	podInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
		AddFunc: func(obj interface{}) {
			pod := obj.(*corev1.Pod)
			LogEvent("添加了", pod)
			// 计数
			mu.Lock()
			count++
			mu.Unlock()
			// fmt.Println("当前pod数量：", count)
		},
		DeleteFunc: func(obj interface{}) {
			pod := obj.(*corev1.Pod)
			LogEvent("删除了", pod)
			mu.Lock()
			count--
			mu.Unlock()
			// fmt.Println("当前pod数量：", count)
		},
	})
	stopch := make(chan struct{})
	go podInformer.Run(stopch) // 启动informer
	// 等待informer完成
	factory.WaitForCacheSync(stopch)
}

// 日志操作(日志内容、Pod)
func LogEvent(cont string, pod *corev1.Pod) {
	// 打开文件
	file, err := os.OpenFile("01.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	defer file.Close()
	if err != nil {
		panic(err)
	}
	// 设置日志的输出位置
	log.SetOutput(file)
	log.Printf("内容：%s  Pod名称:%s", cont, pod.Name)
}

func main() {
	// 创建客户端
	clientset, err := InitClient()
	if err != nil {
		panic(err)
	}
	// fmt.Println("客户端创建成功", clientset)
	// 监听pod
	WatchPods(clientset)

	// 编写周期性的定时器
	// 每隔一段时间往通道中放入一个值
	timer := time.NewTicker(10 * time.Second)
	// 退出之前关闭
	defer timer.Stop()
	// 创建通道，用于关闭定时器
	done := make(chan bool)
	go func() {
		time.Sleep(30 * time.Second)
		done <- true
	}()
	for {
		select {
		case <-timer.C: // 监听是否往通道中放入了值，一旦放入值，就会触发
			fmt.Println("当前pod数量：", count)
			// case <-done:
			// 	fmt.Println("定时器结束")
			// 	return
		}
	}

	// 阻塞主程序
	select {}
}
